package com.ry.thread;

import com.ry.request.InventoryRefreshCacheRequest;
import com.ry.request.InventoryRequest;
import com.ry.request.InventoryRequestQueue;
import com.ry.request.InventoryUpdateDbRequest;
import lombok.extern.slf4j.Slf4j;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;

/**
 * 库存处理线程
 */
@Slf4j
public class InventoryHandleThread implements Callable<Boolean> {

    private ArrayBlockingQueue<InventoryRequest> queue;

    public InventoryHandleThread(ArrayBlockingQueue<InventoryRequest> queue) {
        this.queue = queue;
    }

    // 这是在线程中，不会出现并发问题
    @Override
    public Boolean call() throws Exception {

        while (true){

            InventoryRequest inventoryRequest = queue.take();
            Long productId = inventoryRequest.getProductId();

            // 只有不是强制刷新的请求，才会进行读请求去重处理
            if (!inventoryRequest.isForced()){
                InventoryRequestQueue inventoryRequestQueue = InventoryRequestQueue.getInstance();

                Map<Long, Boolean> flagMap = inventoryRequestQueue.getFlagMap();


                if (inventoryRequest instanceof InventoryUpdateDbRequest){

                    // 说明是写请求先过来
                    flagMap.put(productId,true);
                }else if (inventoryRequest instanceof InventoryRefreshCacheRequest){
                    Boolean flag = flagMap.get(productId);

                    // 说明是读请求先过来
                    if (flag == null){
                        flagMap.put(productId,false);
                    }

                    // 说明前面有过 更新数据库缓存的请求
                    if (flag !=null && flag == true){
                        flagMap.put(productId,false);
                    }

                    // 说明前面有过 更新redis缓存的请求，这次的可以忽略掉
                    // 不需要再次读取数据库更新到redis缓存
                    if (flag !=null && flag == false){
                        continue;
                    }
                }
            }


            log.info("===日志===：工作线程处理请求，商品id={}",productId);
            inventoryRequest.process();

            // 假如说，执行完了一个读请求之后，假设数据已经刷新到redis中了
            // 但是后面可能redis中的数据会因为内存满了，被自动清理掉
            // 如果说数据从redis中被自动清理掉了以后
            // 然后后面又来一个读请求，flagMap中的标志位为false，就不会去执行刷新缓存的操作了
            // 所以在执行完这个读请求之后，实际上这个标志位还是停留在false的
        }

    }
}
